<?php
/**
 * Aero - Xistins Technologies PHP Framework
 * 
 * LICENSE
 * This source file is subject to the New BSD license that is bundled 
 * with this package in the LICENSE.txt. It is also available through 
 * the world-wide-web at this URL: http://dev.xistins.com/license/production
 * If you did not receive a copy of this license and are unable to obtain
 * it through the world-wide-web, please send an email to 
 * license@xistins.com so we can send you a copy immediately.
 * 
 * @category   Aero
 * @package    Aero_Db
 * @subpackage Adapter
 * @copyright  http://dev.xistins.com/license/production     New BSD
 * @version    $Id: Adapter.php 4 2009-11-14 18:35:45Z csouth@xistins.com $
 */

/** @see Aero_Loader */
require_once 'Aero/Loader.php';

/**
 * Base database adapter class
 * 
 * @category   Aero
 * @package    Aero_Db
 * @subpackage Adapter
 * @copyright  http://dev.xistins.com/license/production     New BSD
 * @version    $Id: Adapter.php 4 2009-11-14 18:35:45Z csouth@xistins.com $
 */
abstract class Aero_Db_Adapter
{
    /**
     * Configuration settings
     * @var stdClass
     */
    protected $_config;

    /**
     * Database connection
     * @var mixed
     */
    protected $_connection;

    /**
     * Default Statement Class
     * @var string
     */
    protected $_defaultStatementClass = 'Aero_Db_Statement';

    /**
     * Adapter Constructor
     * 
     * @param  array|stdClass $config
     * @return void
     */
    public function __construct($config)
    {
        $this->_config = $this->_processConfig($config);
    }

    /**
     * Process configuration file
     * 1. Make sure it is of the right type (Convert to stdClass)
     * 2. Check for stdClass, hostname, username, and password.
     * 
     * @param  array|stdClass $config
     * @return stdClass
     */
    protected function _processConfig($config)
    {
        // Check config type
        if(!(array) $config) {
            Aero_Loader::loadClass('Aero_Db_Exception');
            throw new Aero_Db_Exception('Configuration supplied to Aero_Db must either be an array
                                         or a standard object.');
        }
        $config = (object)$config;

        // Check for hostname, username, password, and dbname
        if(!isset($config->host, $config->username, $config->password, $config->dbname)) {
            Aero_Loader::loadClass('Aero_Db_Exception');
            throw new Aero_Db_Exception('Configuration must contain a hostname, username, password, 
                                         and database name for the db connection');
        }

        return $config;
    }

    /**
     * Get the database connection
     * 
     * @return mixed
     */
    public function getConnection()
    {
        if(null === $this->_connection) {
            $this->_connect();
        }

        return $this->_connection;
    }

    /**
     * Prepare a SQL statement
     * 
     * @param  string $sql
     * @return Aero_Db_Statement
     */
    public function prepare($sql)
    {
        if(!is_string($sql)) {
            Aero_Loader::loadClass('Aero_Db_Exception');
            throw new Aero_Db_Exception('Parameter provided to Aero_Db_Adapter::prepare() must be a string.');
        }

        Aero_Loader::loadClass($this->_defaultStatementClass);
        return new $this->_defaultStatementClass($sql, $this);
    }

    /**
     * @todo Select statment coming soon!
     * 
     * public function select($select)
     * {
     *    Aero_Loader::loadClass('Aero_Db_Select');
     *    return new Aero_Db_Select($select);
     * }
     */

    /**
     **********************************************************************************************
     * Abstract Functions
     **********************************************************************************************
     */

    /**
     * Close database connection
     */
    abstract public function closeConnection();

    /**
     * Connect to the database
     */
    abstract protected function _connect();

    /**
     * Describe a table
     */
    abstract public function describeTable($tableName);

    /**
     * Make variable safe for query
     */
    abstract public function escape($var);

    /**
     * Executes a result-less query
     */
    abstract public function exec($sql);

    /**
     * List Tables
     */
    abstract public function listTables($descTables = false);

    /**
     * Query the database
     */
    abstract public function query($sql);
}